package controllers

import (
	"encoding/json"
	"fmt"
	"io"
	"path/filepath"
	"strings"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/beego/beego/v2/server/web"
)

type ShudaoOssController struct {
	web.Controller
}

// OSS配置信息 - 根据测试文件更新配置
var (
	ossBucket    = "gdsc-ai-aqzs"
	ossAccessKey = "fnyfi2f368pbic74d8ll"
	ossSecretKey = "jgqwk7sirqlz2602x2k7yx2eor0vii19wah6ywlv" // 修正SecretKey
	ossEndpoint  = "http://172.16.17.52:8060"                 // 添加http://前缀
	ossRegion    = "us-east-1"
)

// 上传响应结构
type UploadResponse struct {
	StatusCode int    `json:"statusCode"`
	Message    string `json:"message"`
	FileURL    string `json:"fileUrl"`
	FileName   string `json:"fileName"`
	FileSize   int64  `json:"fileSize"`
}

// 获取S3会话
func getS3Session() (*session.Session, error) {
	// 检查时间同步
	now := time.Now()
	utcNow := now.UTC()
	fmt.Printf("=== S3会话创建调试信息 ===\n")
	fmt.Printf("本地时间: %s\n", now.Format("2006-01-02 15:04:05"))
	fmt.Printf("UTC时间: %s\n", utcNow.Format("2006-01-02 15:04:05"))
	fmt.Printf("时间差: %v\n", now.Sub(utcNow))
	fmt.Printf("Bucket: %s\n", ossBucket)
	fmt.Printf("Endpoint: %s\n", ossEndpoint)
	fmt.Printf("Region: %s\n", ossRegion)
	fmt.Printf("AccessKey: %s***\n", ossAccessKey[:8])

	s3Config := &aws.Config{
		Credentials:      credentials.NewStaticCredentials(ossAccessKey, ossSecretKey, ""),
		Endpoint:         aws.String(ossEndpoint),
		Region:           aws.String(ossRegion),
		S3ForcePathStyle: aws.Bool(true), // 使用路径样式而不是虚拟主机样式
		DisableSSL:       aws.Bool(true), // 如果endpoint是http则禁用SSL
		// 添加更多配置选项
		LogLevel: aws.LogLevel(aws.LogDebug), // 启用调试日志
		// 其他配置选项
		MaxRetries: aws.Int(3),
		// 其他配置选项
	}

	// 创建会话
	sess, err := session.NewSession(s3Config)
	if err != nil {
		return nil, err
	}

	// 验证凭据
	_, err = sess.Config.Credentials.Get()
	if err != nil {
		return nil, fmt.Errorf("凭据验证失败: %v", err)
	}

	return sess, nil
}

// 获取UTC时间同步的S3会话（根据测试文件优化配置）
func getUTCS3Session() (*session.Session, error) {
	// 强制使用UTC时间
	utcNow := time.Now().UTC()
	fmt.Printf("=== UTC S3会话创建调试信息 ===\n")
	fmt.Printf("强制使用UTC时间: %s\n", utcNow.Format("2006-01-02 15:04:05"))
	fmt.Printf("Bucket: %s\n", ossBucket)
	fmt.Printf("Endpoint: %s\n", ossEndpoint)
	fmt.Printf("Region: %s\n", ossRegion)
	fmt.Printf("AccessKey: %s***\n", ossAccessKey[:8])

	// 创建S3配置 - 使用与测试文件相同的配置
	s3Config := &aws.Config{
		Credentials:      credentials.NewStaticCredentials(ossAccessKey, ossSecretKey, ""),
		Endpoint:         aws.String(ossEndpoint),
		Region:           aws.String(ossRegion),
		S3ForcePathStyle: aws.Bool(true), // 强制使用路径样式（OSS兼容性需要）
		// 移除DisableSSL，因为endpoint已经包含http://
		// 移除LogLevel，减少调试输出
		// 移除MaxRetries，使用默认值
		// 移除S3DisableContentMD5Validation，使用默认值
	}

	// 创建会话
	sess, err := session.NewSession(s3Config)
	if err != nil {
		return nil, err
	}

	// 验证凭据
	_, err = sess.Config.Credentials.Get()
	if err != nil {
		return nil, fmt.Errorf("凭据验证失败: %v", err)
	}

	return sess, nil
}

// 判断是否为图片文件
func isImageFile(ext string) bool {
	imageExts := map[string]bool{
		".jpg":  true,
		".jpeg": true,
		".png":  true,
		".gif":  true,
		".bmp":  true,
		".webp": true,
		".tiff": true,
		".svg":  true,
		".ico":  true,
	}
	return imageExts[ext]
}

// 图片上传接口
func (c *ShudaoOssController) UploadImage() {
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "Content-Type")

	if c.Ctx.Request.Method == "OPTIONS" {
		c.Ctx.ResponseWriter.WriteHeader(200)
		return
	}

	// 获取上传的图片文件
	file, header, err := c.GetFile("image")
	if err != nil {
		c.Data["json"] = UploadResponse{
			StatusCode: 400,
			Message:    "获取上传图片失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}
	defer file.Close()

	// 检查文件扩展名
	ext := strings.ToLower(filepath.Ext(header.Filename))
	if !isImageFile(ext) {
		c.Data["json"] = UploadResponse{
			StatusCode: 400,
			Message:    "不支持的文件格式，请上传图片文件（jpg, png, gif, bmp, webp等）",
		}
		c.ServeJSON()
		return
	}

	// 图片文件大小限制（10MB）
	if header.Size > 10*1024*1024 {
		c.Data["json"] = UploadResponse{
			StatusCode: 400,
			Message:    "图片文件大小超过限制（10MB）",
		}
		c.ServeJSON()
		return
	}

	// 生成图片文件名（使用UTC时间）
	utcNow := time.Now().UTC()
	timestamp := utcNow.Unix()
	fileName := fmt.Sprintf("images/%d/%s_%d%s",
		utcNow.Year(),
		utcNow.Format("0102"),
		timestamp,
		ext)

	// 读取图片内容
	fileBytes, err := io.ReadAll(file)
	if err != nil {
		c.Data["json"] = UploadResponse{
			StatusCode: 500,
			Message:    "读取图片内容失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 获取UTC时间同步的S3会话（解决时区问题）
	sess, err := getUTCS3Session()
	if err != nil {
		c.Data["json"] = UploadResponse{
			StatusCode: 500,
			Message:    "创建S3会话失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 创建S3服务
	s3Client := s3.New(sess)

	// 打印上传信息
	fmt.Printf("正在上传图片: %s\n", fileName)
	fmt.Printf("文件大小: %d bytes\n", len(fileBytes))
	fmt.Printf("ContentType: %s\n", header.Header.Get("Content-Type"))

	// 上传图片到S3 - 使用与测试文件相同的上传方式
	_, err = s3Client.PutObject(&s3.PutObjectInput{
		Bucket: aws.String(ossBucket),
		Key:    aws.String(fileName),
		Body:   aws.ReadSeekCloser(strings.NewReader(string(fileBytes))), // 使用与测试文件相同的方式
		ACL:    aws.String("public-read"),
	})

	if err != nil {
		fmt.Printf("上传图片失败: %v\n", err)
		c.Data["json"] = UploadResponse{
			StatusCode: 500,
			Message:    "上传图片到OSS失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// // 生成预签名URL（1小时有效期）
	// req, _ := s3Client.GetObjectRequest(&s3.GetObjectInput{
	// 	Bucket: aws.String(ossBucket),
	// 	Key:    aws.String(fileName),
	// })

	// presignedURL, err := req.Presign(24 * time.Hour)
	// if err != nil {
	// 	fmt.Printf("生成预签名URL失败: %v\n", err)
	// 	// 如果预签名URL生成失败，使用简单URL作为备选
	// 	imageURL := fmt.Sprintf("%s/%s", ossEndpoint, fileName)
	// 	c.Data["json"] = UploadResponse{
	// 		StatusCode: 200,
	// 		Message:    "图片上传成功，但预签名URL生成失败",
	// 		FileURL:    imageURL,
	// 		FileName:   fileName,
	// 		FileSize:   header.Size,
	// 	}
	// 	c.ServeJSON()
	// 	return
	// }
	permanentURL := fmt.Sprintf("%s/%s/%s", ossEndpoint, ossBucket, fileName)
	fmt.Printf("图片上传成功: %s\n", fileName)
	fmt.Printf("预签名URL: %s\n", permanentURL)

	c.Data["json"] = UploadResponse{
		StatusCode: 200,
		Message:    "图片上传成功",
		FileURL:    permanentURL,
		FileName:   fileName,
		FileSize:   header.Size,
	}
	c.ServeJSON()
}

// 上传PPTjson文件
func (c *ShudaoOssController) UploadPPTJson() {
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
	c.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "Content-Type")

	if c.Ctx.Request.Method == "OPTIONS" {
		c.Ctx.ResponseWriter.WriteHeader(200)
		return
	}

	// 获取上传的JSON文件
	file, header, err := c.GetFile("json")
	if err != nil {
		c.Data["json"] = UploadResponse{
			StatusCode: 400,
			Message:    "获取上传JSON文件失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}
	defer file.Close()

	// 检查文件扩展名
	ext := strings.ToLower(filepath.Ext(header.Filename))
	if ext != ".json" {
		c.Data["json"] = UploadResponse{
			StatusCode: 400,
			Message:    "不支持的文件格式，请上传JSON文件（.json）",
		}
		c.ServeJSON()
		return
	}

	// JSON文件大小限制（50MB）
	if header.Size > 50*1024*1024 {
		c.Data["json"] = UploadResponse{
			StatusCode: 400,
			Message:    "JSON文件大小超过限制（50MB）",
		}
		c.ServeJSON()
		return
	}

	// 生成JSON文件名（使用UTC时间）
	utcNow := time.Now().UTC()
	timestamp := utcNow.Unix()
	fileName := fmt.Sprintf("json/%d/%s_%d%s",
		utcNow.Year(),
		utcNow.Format("0102"),
		timestamp,
		ext)

	// 读取JSON内容
	fileBytes, err := io.ReadAll(file)
	if err != nil {
		c.Data["json"] = UploadResponse{
			StatusCode: 500,
			Message:    "读取JSON内容失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 验证JSON格式
	var jsonData interface{}
	if err := json.Unmarshal(fileBytes, &jsonData); err != nil {
		c.Data["json"] = UploadResponse{
			StatusCode: 400,
			Message:    "JSON格式无效: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 获取UTC时间同步的S3会话
	sess, err := getUTCS3Session()
	if err != nil {
		c.Data["json"] = UploadResponse{
			StatusCode: 500,
			Message:    "创建S3会话失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 创建S3服务
	s3Client := s3.New(sess)

	// 打印上传信息
	fmt.Printf("正在上传JSON文件: %s\n", fileName)
	fmt.Printf("文件大小: %d bytes\n", len(fileBytes))
	fmt.Printf("ContentType: %s\n", header.Header.Get("Content-Type"))

	// 上传JSON到S3
	_, err = s3Client.PutObject(&s3.PutObjectInput{
		Bucket:      aws.String(ossBucket),
		Key:         aws.String(fileName),
		Body:        aws.ReadSeekCloser(strings.NewReader(string(fileBytes))),
		ACL:         aws.String("public-read"),
		ContentType: aws.String("application/json"),
	})

	if err != nil {
		fmt.Printf("上传JSON文件失败: %v\n", err)
		c.Data["json"] = UploadResponse{
			StatusCode: 500,
			Message:    "上传JSON文件到OSS失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 生成永久URL
	permanentURL := fmt.Sprintf("%s/%s/%s", ossEndpoint, ossBucket, fileName)
	fmt.Printf("JSON文件上传成功: %s\n", fileName)
	fmt.Printf("文件URL: %s\n", permanentURL)

	c.Data["json"] = UploadResponse{
		StatusCode: 200,
		Message:    "JSON文件上传成功",
		FileURL:    permanentURL,
		FileName:   fileName,
		FileSize:   header.Size,
	}
	c.ServeJSON()
}
